Skip to content

CAMEL-24046 - avoid system property leak to other tests from ZXsltTotalOpsTest#24955

Merged
apupier merged 1 commit into
apache:mainfrom
apupier:CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest
Jul 22, 2026
Merged

CAMEL-24046 - avoid system property leak to other tests from ZXsltTotalOpsTest#24955
apupier merged 1 commit into
apache:mainfrom
apupier:CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest

Conversation

@apupier

@apupier apupier commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

when it is failing, usually the 2nd and 3rd run are failing with:

org.apache.camel.FailedToCreateRouteException: Failed to create route:
route8150 at: >>> to[xslt:org/apache/camel/component/xslt/example.xsl]
<<< in route:
Route(route8150)[From[file:/tmp/junit-11867091151342813293?m... because:
Failed to resolve endpoint:
xslt://org/apache/camel/component/xslt/example.xsl due to:
javax.xml.transform.TransformerConfigurationException: JAXP0801003: the
compiler encountered XPath expressions with an accumulated '2' operators
that exceeds the '1' limit set by 'system property'.

When I checked on the workspace filesystem of a failed build the file camel-core/target/test-classes/org/apache/camel/component/xslt/example.xsl seems fine.
But maybe the file is locked at that time or modified temporarily by another test, so modified the test to use a specific xsl file for this test class.

Note that it doesn't impact the first flaky failure which is usually another error.

I propose to first try this way to see if we can get rid of the 2nd and 3rd failure, which are causing the build to fail. if there is only the first attempt failing, it is not nice but only flaky and few seconds are lost.

Description

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • I checked that each commit in the pull request has a meaningful subject line and body.
  • I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.

AI-assisted contributions

  • If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., Co-authored-by trailers) and the PR description identifies the AI tool used.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, pragmatic approach to reducing the flakiness of XsltFromFileExceptionTest.

What works well:

  • The dedicated XSL file (example-file-exception-test.xsl) isolates this test from the ~16 other tests that reference example.xsl, eliminating potential resource contention through JAXP's TransformerFactory caching layer
  • The new file is an exact copy of example.xsl — no behavioral change to the test logic
  • The PR description is honest about scope: this targets the 2nd/3rd retry failures (the JAXP0801003 operator-limit error), not necessarily the first failure mode

Minor observation (non-blocking): The JAXP0801003 error about XPath operator limits (accumulated '2' operators exceeds the '1' limit set by 'system property') could also stem from another test setting jdk.xml.xpathExprOpLimit via System.setProperty without restoring it. File isolation helps with TransformerFactory cache contention but wouldn't fix a JVM-wide system property leak. Worth investigating separately if the flakiness persists after this change.

Overall, a sensible incremental fix — reduces the blast radius without over-engineering it. 👍

Claude Code on behalf of gnodet — AI-generated review

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions github-actions Bot added the core label Jul 20, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • core/camel-core

🔬 Scalpel shadow comparison — Scalpel: 23 tested, 0 compile-only — current: 0 all tested

Maveniverse Scalpel detected 23 affected modules (current approach: 0).

⚠️ Modules only in Scalpel (23)
  • camel-console
  • camel-core
  • camel-csimple-joor
  • camel-datasonnet
  • camel-groovy
  • camel-hl7
  • camel-javascript
  • camel-joor
  • camel-jq
  • camel-jsonpath
  • camel-main
  • camel-management
  • camel-mvel
  • camel-ognl
  • camel-platform-http-jolokia
  • camel-python
  • camel-saxon
  • camel-spring-xml
  • camel-stax
  • camel-xml-io-dsl
  • camel-xml-jaxb-dsl
  • camel-xml-jaxb-dsl-test-definition
  • camel-xml-jaxb-dsl-test-spring

Skip-tests mode would test 23 modules (1 direct + 22 downstream), skip tests for 0 (generated code, meta-modules)

Modules Scalpel would test (23)
  • camel-console
  • camel-core
  • camel-csimple-joor
  • camel-datasonnet
  • camel-groovy
  • camel-hl7
  • camel-javascript
  • camel-joor
  • camel-jq
  • camel-jsonpath
  • camel-main
  • camel-management
  • camel-mvel
  • camel-ognl
  • camel-platform-http-jolokia
  • camel-python
  • camel-saxon
  • camel-spring-xml
  • camel-stax
  • camel-xml-io-dsl
  • camel-xml-jaxb-dsl
  • camel-xml-jaxb-dsl-test-definition
  • camel-xml-jaxb-dsl-test-spring

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • core/camel-core: 2 test(s) disabled on GitHub Actions
All tested modules (23 modules)
  • Camel :: Console
  • Camel :: Core
  • Camel :: DataSonnet
  • Camel :: Groovy
  • Camel :: HL7
  • Camel :: JQ
  • Camel :: JSon Path
  • Camel :: JavaScript
  • Camel :: MVEL
  • Camel :: Main
  • Camel :: Management
  • Camel :: OGNL (deprecated)
  • Camel :: Platform HTTP :: Jolokia
  • Camel :: Python
  • Camel :: Saxon
  • Camel :: Spring XML
  • Camel :: StAX
  • Camel :: XML DSL Jaxb :: Test :: Definition
  • Camel :: XML DSL Jaxb :: Test :: Spring
  • Camel :: XML DSL with camel-xml-io
  • Camel :: XML DSL with camel-xml-jaxb
  • Camel :: csimple jOOR (deprecated)
  • Camel :: jOOR

⚙️ View full build and test results

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating my earlier review after investigating the root cause of the flakiness.

Root cause: system property leak from ZXsltTotalOpsTest

The JAXP error in the 2nd/3rd retries —

JAXP0801003: the compiler encountered XPath expressions with an accumulated '2'
operators that exceeds the '1' limit set by 'system property'.

— is caused by ZXsltTotalOpsTest (same package) leaking jdk.xml.xpathTotalOpLimit=1 via System.setProperty.

Here's the chain:

  1. ZXsltTotalOpsTest calls xslt.setXpathTotalOpLimit(1), which triggers System.setProperty("jdk.xml.xpathTotalOpLimit", "1") during XsltComponent.doInit()
  2. The test expects context.start() to throw (the XSL has 2 operators > limit of 1)
  3. Cleanup relies on XsltComponent.doShutdown() calling System.clearProperty() — but when context.start() fails mid-way, the shutdown path may not fully execute
  4. When XsltFromFileExceptionTest retries (after its 1st failure for a different reason), the leaked property causes any XSL compilation with >1 operator to fail

This matches your observation exactly: the 1st failure has a different cause, then ZXsltTotalOpsTest runs during the retry window, leaks the property, and retries 2 and 3 hit the JAXP limit.

Why a dedicated XSL file won't fix this

The new example-file-exception-test.xsl has 2 XPath operators (match="/" + select="/hello") — identical to example.xsl. When jdk.xml.xpathTotalOpLimit=1 is leaked, any XSL file with >1 operator fails regardless of its path. File isolation addresses TransformerFactory cache contention, but the error is a JVM-wide system property issue.

Suggested fix

Ensure ZXsltTotalOpsTest cleans up the system property reliably, similar to how XPathFeatureTest handles it (with @ResourceLock(Resources.SYSTEM_PROPERTIES) + try/finally):

@Isolated
@ResourceLock(Resources.SYSTEM_PROPERTIES)
public class ZXsltTotalOpsTest extends ContextTestSupport {

    @AfterEach
    void clearXpathLimit() {
        System.clearProperty("jdk.xml.xpathTotalOpLimit");
    }
    // ... rest unchanged
}

Adding @AfterEach guarantees the property is cleared even when context.start() throws and the CamelContext lifecycle doesn't fully unwind. The @ResourceLock annotation prevents other system-property-sensitive tests from running concurrently.

Claude Code on behalf of gnodet — AI-generated review

@apupier

apupier commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

the 2nd and 3rd failure are occuring after

[INFO] Running org.apache.camel.component.xslt.ZXsltTotalOpsTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 s -- in org.apache.camel.component.xslt.ZXsltTotalOpsTest

but the test is in success and it is significantly after, so it sounds like there is a bug that doesn't set back the property

@apupier

apupier commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

reported https://issues.apache.org/jira/browse/CAMEL-24216 to fix the spotted issue correctly and wil provide the workaround by unsetting the system property in tear down

@apupier
apupier force-pushed the CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest branch from 5430ded to 1cd0c36 Compare July 21, 2026 12:06
@apupier apupier changed the title CAMEL-24046 - attempt to avoid flakiness of XsltFromFileExceptionTest by using specific xsl file CAMEL-24046 - avoid system property leak to other tests Jul 21, 2026
@apupier apupier changed the title CAMEL-24046 - avoid system property leak to other tests CAMEL-24046 - avoid system property leak to other tests from ZXsltTotalOpsTest Jul 21, 2026
@apupier
apupier force-pushed the CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest branch from 1cd0c36 to d8e87d8 Compare July 21, 2026 12:10
ZXsltTotalOpsTest

due to https://issues.apache.org/jira/browse/CAMEL-24216 , a system
property is leaking to other tests. it can impact other tests to fail
when they are played after it. For instance when
XsltFromFileExceptionTest is flaky, the 2nd and 3rd run are launched
after it and are failing.

Signed-off-by: Aurélien Pupier <apupier@ibm.com>
@apupier
apupier force-pushed the CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest branch from d8e87d8 to b7f4acd Compare July 21, 2026 13:01
@apupier
apupier requested a review from gnodet July 21, 2026 14:28
@apupier
apupier marked this pull request as ready for review July 21, 2026 14:28

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code on behalf of gnodet

LGTM — thanks for addressing the review feedback!

The updated approach is exactly right: the @AfterEach cleanup on ZXsltTotalOpsTest ensures jdk.xml.xpathTotalOpLimit is cleared even when context.start() throws and the CamelContext lifecycle doesn't fully unwind. This fixes the root cause (system property leak) rather than working around it with file isolation.

One optional follow-up: adding @ResourceLock(Resources.SYSTEM_PROPERTIES) (from JUnit 5 parallel execution) would additionally prevent concurrent test runs from racing on the system property. Not a blocker for this PR though.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @AfterEach cleanup prevents the leak — nice and simple. However, the test mutates system properties via System.setProperty("jdk.xml.xpathTotalOpLimit", ...) (inside XsltComponent.setXpathTotalOpLimit(1)), so it should also declare a write-mode @ResourceLock:

import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.api.parallel.Resources;

@Isolated
@ResourceLock(Resources.SYSTEM_PROPERTIES)
public class ZXsltTotalOpsTest extends ContextTestSupport {

Why: TestSupport (the grandparent) declares @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = READ), telling JUnit this test only reads system properties. Since this test writes them, the inherited declaration is incorrect — it should be overridden with the default (READ_WRITE) mode.

@Isolated already prevents concurrent execution, so this is not a functional bug today, but it's defense in depth and makes the contract explicit.

@apupier

apupier commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

The @AfterEach cleanup prevents the leak — nice and simple. However, the test mutates system properties via System.setProperty("jdk.xml.xpathTotalOpLimit", ...) (inside XsltComponent.setXpathTotalOpLimit(1)), so it should also declare a write-mode @ResourceLock:

import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.api.parallel.Resources;

@Isolated
@ResourceLock(Resources.SYSTEM_PROPERTIES)
public class ZXsltTotalOpsTest extends ContextTestSupport {

Why: TestSupport (the grandparent) declares @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = READ), telling JUnit this test only reads system properties. Since this test writes them, the inherited declaration is incorrect — it should be overridden with the default (READ_WRITE) mode.

@Isolated already prevents concurrent execution, so this is not a functional bug today, but it's defense in depth and makes the contract explicit.

I will provide a different PR for that as it is not directly related to the initial intent of this PR

@apupier
apupier merged commit 1a11849 into apache:main Jul 22, 2026
5 checks passed
@apupier
apupier deleted the CAMEl-24026-avoidFlakinessofXsltFromFileExceptionTest branch July 22, 2026 12:13
apupier added a commit that referenced this pull request Jul 23, 2026
TestSupport (the grandparent) declares @ResourceLock(value =
Resources.SYSTEM_PROPERTIES, mode = READ), telling JUnit this test only
reads system properties. Since this test writes them, the inherited
declaration is incorrect — it should be overridden with the default
(READ_WRITE) mode.

follows-up to
#24955 (review)

Signed-off-by: Aurélien Pupier <apupier@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants